import type { RGBColor, HSLColor, HSVColor } from './types'

/**
 * 颜色工具函数集合
 */
export class ColorUtils {
  /**
   * 十六进制转RGB
   * @param hex 十六进制颜色值
   * @returns RGB颜色对象或null
   */
  static hexToRgb(hex: string): RGBColor | null {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
    if (result) {
      return {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
      }
    }
    return null
  }

  /**
   * RGB转十六进制
   * @param r 红色值 (0-255)
   * @param g 绿色值 (0-255)
   * @param b 蓝色值 (0-255)
   * @returns 十六进制颜色值
   */
  static rgbToHex(r: number, g: number, b: number): string {
    const toHex = (n: number) => {
      const hex = Math.round(n).toString(16)
      return hex.length === 1 ? '0' + hex : hex
    }
    return `#${toHex(r)}${toHex(g)}${toHex(b)}`
  }

  /**
   * RGB转HSL
   * @param r 红色值 (0-255)
   * @param g 绿色值 (0-255)
   * @param b 蓝色值 (0-255)
   * @returns HSL颜色对象
   */
  static rgbToHsl(r: number, g: number, b: number): HSLColor {
    r /= 255
    g /= 255
    b /= 255

    const max = Math.max(r, g, b)
    const min = Math.min(r, g, b)
    let h = 0
    let s = 0
    const l = (max + min) / 2

    if (max !== min) {
      const d = max - min
      s = l > 0.5 ? d / (2 - max - min) : d / (max + min)

      switch (max) {
        case r:
          h = (g - b) / d + (g < b ? 6 : 0)
          break
        case g:
          h = (b - r) / d + 2
          break
        case b:
          h = (r - g) / d + 4
          break
      }
      h /= 6
    }

    return {
      h: Math.round(h * 360),
      s: Math.round(s * 100),
      l: Math.round(l * 100)
    }
  }

  /**
   * HSL转RGB
   * @param h 色相 (0-360)
   * @param s 饱和度 (0-100)
   * @param l 亮度 (0-100)
   * @returns RGB颜色对象
   */
  static hslToRgb(h: number, s: number, l: number): RGBColor {
    h /= 360
    s /= 100
    l /= 100

    const hue2rgb = (p: number, q: number, t: number) => {
      if (t < 0) t += 1
      if (t > 1) t -= 1
      if (t < 1/6) return p + (q - p) * 6 * t
      if (t < 1/2) return q
      if (t < 2/3) return p + (q - p) * (2/3 - t) * 6
      return p
    }

    let r, g, b

    if (s === 0) {
      r = g = b = l
    } else {
      const q = l < 0.5 ? l * (1 + s) : l + s - l * s
      const p = 2 * l - q
      r = hue2rgb(p, q, h + 1/3)
      g = hue2rgb(p, q, h)
      b = hue2rgb(p, q, h - 1/3)
    }

    return {
      r: Math.round(r * 255),
      g: Math.round(g * 255),
      b: Math.round(b * 255)
    }
  }

  /**
   * RGB转HSV
   * @param r 红色值 (0-255)
   * @param g 绿色值 (0-255)
   * @param b 蓝色值 (0-255)
   * @returns HSV颜色对象
   */
  static rgbToHsv(r: number, g: number, b: number): HSVColor {
    r /= 255
    g /= 255
    b /= 255

    const max = Math.max(r, g, b)
    const min = Math.min(r, g, b)
    const d = max - min
    let h = 0
    const s = max === 0 ? 0 : d / max
    const v = max

    if (max !== min) {
      switch (max) {
        case r:
          h = (g - b) / d + (g < b ? 6 : 0)
          break
        case g:
          h = (b - r) / d + 2
          break
        case b:
          h = (r - g) / d + 4
          break
      }
      h /= 6
    }

    return {
      h: Math.round(h * 360),
      s: Math.round(s * 100),
      v: Math.round(v * 100)
    }
  }

  /**
   * HSV转RGB
   * @param h 色相 (0-360)
   * @param s 饱和度 (0-100)
   * @param v 明度 (0-100)
   * @returns RGB颜色对象
   */
  static hsvToRgb(h: number, s: number, v: number): RGBColor {
    h /= 360
    s /= 100
    v /= 100

    const i = Math.floor(h * 6)
    const f = h * 6 - i
    const p = v * (1 - s)
    const q = v * (1 - f * s)
    const t = v * (1 - (1 - f) * s)

    let r, g, b

    switch (i % 6) {
      case 0:
        r = v
        g = t
        b = p
        break
      case 1:
        r = q
        g = v
        b = p
        break
      case 2:
        r = p
        g = v
        b = t
        break
      case 3:
        r = p
        g = q
        b = v
        break
      case 4:
        r = t
        g = p
        b = v
        break
      case 5:
        r = v
        g = p
        b = q
        break
      default:
        r = g = b = 0
    }

    return {
      r: Math.round(r * 255),
      g: Math.round(g * 255),
      b: Math.round(b * 255)
    }
  }

  /**
   * 验证颜色格式
   * @param color 颜色值
   * @returns 是否为有效颜色
   */
  static isValidColor(color: string): boolean {
    // 十六进制格式
    if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color)) {
      return true
    }

    // RGB格式
    if (/^rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)$/.test(color)) {
      return true
    }

    // RGBA格式
    if (/^rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*[0-9.]+\s*\)$/.test(color)) {
      return true
    }

    // HSL格式
    if (/^hsl\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*\)$/.test(color)) {
      return true
    }

    // HSLA格式
    if (/^hsla\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*,\s*[0-9.]+\s*\)$/.test(color)) {
      return true
    }

    return false
  }

  /**
   * 获取颜色亮度
   * @param r 红色值 (0-255)
   * @param g 绿色值 (0-255)
   * @param b 蓝色值 (0-255)
   * @returns 亮度值 (0-1)
   */
  static getLuminance(r: number, g: number, b: number): number {
    const [rs, gs, bs] = [r, g, b].map(c => {
      c = c / 255
      return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
    })
    return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs
  }

  /**
   * 获取对比色
   * @param r 红色值 (0-255)
   * @param g 绿色值 (0-255)
   * @param b 蓝色值 (0-255)
   * @returns 对比色（黑色或白色）
   */
  static getContrastColor(r: number, g: number, b: number): string {
    const luminance = this.getLuminance(r, g, b)
    return luminance > 0.5 ? '#000000' : '#FFFFFF'
  }

  /**
   * 解析颜色字符串
   * @param color 颜色字符串
   * @returns RGB颜色对象或null
   */
  static parseColor(color: string): RGBColor | null {
    // 移除空格
    color = color.trim()

    // 十六进制格式
    if (color.startsWith('#')) {
      return this.hexToRgb(color)
    }

    // RGB格式
    const rgbMatch = color.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/)
    if (rgbMatch) {
      return {
        r: parseInt(rgbMatch[1]),
        g: parseInt(rgbMatch[2]),
        b: parseInt(rgbMatch[3])
      }
    }

    // RGBA格式
    const rgbaMatch = color.match(/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([0-9.]+)\s*\)$/)
    if (rgbaMatch) {
      return {
        r: parseInt(rgbaMatch[1]),
        g: parseInt(rgbaMatch[2]),
        b: parseInt(rgbaMatch[3])
      }
    }

    // HSL格式
    const hslMatch = color.match(/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$/)
    if (hslMatch) {
      const h = parseInt(hslMatch[1])
      const s = parseInt(hslMatch[2])
      const l = parseInt(hslMatch[3])
      return this.hslToRgb(h, s, l)
    }

    // HSLA格式
    const hslaMatch = color.match(/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([0-9.]+)\s*\)$/)
    if (hslaMatch) {
      const h = parseInt(hslaMatch[1])
      const s = parseInt(hslaMatch[2])
      const l = parseInt(hslaMatch[3])
      return this.hslToRgb(h, s, l)
    }

    return null
  }

  /**
   * 格式化颜色值
   * @param color RGB颜色对象
   * @param format 输出格式
   * @returns 格式化后的颜色字符串
   */
  static formatColor(color: RGBColor, format: 'hex' | 'rgb' | 'rgba' = 'hex'): string {
    switch (format) {
      case 'hex':
        return this.rgbToHex(color.r, color.g, color.b)
      case 'rgb':
        return `rgb(${color.r}, ${color.g}, ${color.b})`
      case 'rgba':
        return `rgba(${color.r}, ${color.g}, ${color.b}, 1)`
      default:
        return this.rgbToHex(color.r, color.g, color.b)
    }
  }

  /**
   * 生成随机颜色
   * @returns 随机十六进制颜色
   */
  static generateRandomColor(): string {
    const letters = '0123456789ABCDEF'
    let color = '#'
    for (let i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)]
    }
    return color
  }

  /**
   * 生成颜色渐变
   * @param startColor 起始颜色
   * @param endColor 结束颜色
   * @param steps 步数
   * @returns 颜色数组
   */
  static generateGradient(startColor: string, endColor: string, steps: number): string[] {
    const start = this.parseColor(startColor)
    const end = this.parseColor(endColor)
    
    if (!start || !end) {
      return []
    }

    const colors: string[] = []
    for (let i = 0; i < steps; i++) {
      const ratio = i / (steps - 1)
      const r = Math.round(start.r + (end.r - start.r) * ratio)
      const g = Math.round(start.g + (end.g - start.g) * ratio)
      const b = Math.round(start.b + (end.b - start.b) * ratio)
      colors.push(this.rgbToHex(r, g, b))
    }

    return colors
  }
} 